/*
* 创建并编译一个着色器
*
* @param {!WebGLRenderingContext} gl WebGL 上下文
* @param {string} shaderSource GLSL 格式的着色器代码
* @param {number} shaderType 着色器类型， gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER
*
* @return {!WebGLShader} 着色器
* */
function compileShader(gl, shaderSource, shaderType) {
    // 创建指定类型的着色器
    let shader = gl.createShader(shaderType);
    // 设置着色器源码
    gl.shaderSource(shader, shaderSource);
    // 编译着色器
    gl.compileShader(shader);
    // 检测编译是否成功
    let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (!success) {
        throw new Error(`could not compile shader: ${gl.getShaderInfoLog(shader)}`);
    }
    return shader;
}

/*
* 使用script标签的内容创建着色器
*
* @param {!WebGLRenderingContext} gl WebGL 上下文
* @param {string} scriptId script标签的id
* @param {number} shaderType 要创建的着色器类型（gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER），如果没有定义，就使用script标签的type属性
*
* @return {!WebGLShader} 着色器
* */
function createShaderFromScript(gl, scriptId, shaderType) {
    // 通过scriptId找到script标签
    let shaderScript = document.querySelector(scriptId);
    if (!shaderScript) {
        throw new Error(`*** Error: unknown script element ${scriptId}`);
    }

    // 提取标签内容
    let shaderScource = shaderScript.text;

    // 如果没有传入着色器类型，就使用script标签的'type'属性
    if (!shaderType) {
        if (!shaderScript.type) {
            throw new Error(`*** Error: shader type not set on script tag which id is: ${scriptId}`);
        }
        if (shaderScript.type === "x-shader/x-vertex") {
            shaderType = gl.VERTEX_SHADER;
        }else if (shaderScript.type === "x-shader/x-fragment") {
            shaderType = gl.FRAGMENT_SHADER;
        } else {
            throw new Error(`*** Error: invalid value of shader type on script tag which id is: ${scriptId}`);
        }
    }
    return compileShader(gl, shaderScource, shaderType);
}

/*
* 从2个着色器中创建着色器程序
*
* @param {!WebGLRenderingContext} gl WebGL 上下文
* @param {!WebGLShader} vertexShader 定点着色器
* @param {!WebGLShader} fragmentShader 片段着色器
*
* @return {!WebGLProgram} 着色器程序
* */
function createProgram(gl, vertexShader, fragmentShader) {
    // 创建着色器程序
    let program = gl.createProgram();
    // 关联着色器
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    // 链接到程序
    gl.linkProgram(program);
    // 检测链接是否成功
    let success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (!success) {
        throw new Error(`program failed to link: ${gl.getProgramInfoLog(program)}`);
    }
    return program;
}

/*
* 通过两个script标签创建着色器程序
*
* @param {!WebGLRenderingContext} gl WebGL 上下文
* @param {string} vertexShaderScriptId 定点着色器script标签id
* @param {string} fragmentShaderScriptId 片段着色器script标签id
*
* @return {!WebGLProgram} 着色器程序
* */
function createProgramFromScripts(gl, vertexShaderScriptId, fragmentShaderScriptId) {
    let vertexShader = createShaderFromScript(gl, vertexShaderScriptId, gl.VERTEX_SHADER);
    let fragmentShader = createShaderFromScript(gl, fragmentShaderScriptId, gl.FRAGMENT_SHADER);
    return createProgram(gl, vertexShader, fragmentShader);
}

/*
* 重置像素尺寸为画布的尺寸
*
* @param {!CanvasHTMLElement} canvas canvas 元素
* */
function resize(canvas) {
    let displayWidth = canvas.clientWidth;
    let displayHeight = canvas.clientHeight;

    if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
        canvas.width = displayWidth;
        canvas.height = displayHeight;
    }
}
